﻿using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.Devices;
using HamcoWcs.Models.Events;
using System;
using System.Collections.Generic;
using System.Linq;

namespace HamcoWcs.Models.NodeInfos
{
    public class NodeInfoDto
    {
        public string NodeName { get; set; }
        public string NextNode { get; set; }
        public string InName { get; set; }
        public string OutName { get; set; }
        public EnumNodeType DeviceType { get; set; }
        public string AlternateNode { get; set; }
        public int FPriority { get; set; }
        public int TPriority { get; set; }

        public bool IsError { get; set; }
        public DateTime ErrorTime { get; set; }

        public List<PconDto> Pcons { get; set; } = new List<PconDto>();
        public EnumMachineControlState MachineControlState { get; set; }
        public EnumMachineState MachineState { get; set; }
        public bool IsNeedReport { get; set; } = false;
        public DateTime CreatTime { get; set; } = DateTime.Now;
        public ICollection<SrmDto> Srms => SrmPlc.Srms.Values;
        public SrmPlc SrmPlc { get; set; }

        public EnumSrmAisleMode AisleMode { get; set; } = EnumSrmAisleMode.Normal;
        public EnumRgvMode RgvMode { get; set; } = EnumRgvMode.Normal;

        /// <summary>
        /// 输送方向
        /// </summary>
        public EnumPconWorkType PconWorkType { get; set; } = EnumPconWorkType.In;

        public event EventHandler<StateChangeEvent> StatusChangeEvent;


        public bool UpdateControlState()
        {
            var old = MachineControlState;
            int t = 0;
            if (Pcons.Any(x => x.WorkType == 4) || Pcons.Any(x => x.PconMode == 2 || x.PconMode == 3 || x.PconMode == 4 || x.PconMode == 5 || x.PconMode == 8))
                t = 1;
            else if (Pcons.Any(x => x.PconMode == 0))
                t = 2;


            this.MachineControlState = t switch
            {
                1 => EnumMachineControlState.ONLINELOCAL,
                2 => EnumMachineControlState.OFFLINE,
                _ => EnumMachineControlState.ONLINEREMOTE
            };

            return old != this.MachineControlState;
        }
        public bool UpdateState()
        {
            var old = MachineState;
            int t = 0;
            var needIdlePcons = new List<string>() { "CJMIFB00", "CJMIFC00", "CJRGV100", "CJRGV200" };
            if (Pcons.Any(x => x.PconMode == 4))
                t = 1;
            else if (Pcons.Any(x => x.PconMode == 2))
                t = 1;
            else if (Pcons.Any(x => x.PconMode == 3))
                t = 1;
            else if (Pcons.Any(x => x.PconMode == 5))
                t = 1;
            //t = 2;
            else if (Pcons.Any(x => x.PconMode == 8))
                t = 3;
            else if (Pcons.All(x => x.PconMode == 1 && x.IsGoods == 0) && MachineState != EnumMachineState.DOWN && needIdlePcons.Contains(NodeName))
                t = 4;

            this.MachineState = t switch
            {
                1 => EnumMachineState.DOWN,
                2 => EnumMachineState.PM,
                3 => EnumMachineState.BLOCK,
                4 => EnumMachineState.IDLE,
                _ => EnumMachineState.RUN
            };

            return old != MachineState;
        }
        public void UpdatePconState()
        {
            var needPcons = new List<string>() { "CJMIFB00", "CJMIFC00", "CJRGV100", "CJRGV200" };
            var items = Pcons.Where(x => needPcons.Contains(x.MachineName)).ToList();
            items.
                Where(x =>
                x.PconMode == 2 || x.PconMode == 3 || x.PconMode == 4 || x.PconMode == 5).
                ToList().
                ForEach(x =>
                {
                    x.MachineState = EnumMachineState.DOWN;
                });
            items.
                Where(x =>
                x.PconMode == 1 && x.IsGoods == 0).
                ToList().
                ForEach(x =>
                {
                    x.MachineState = EnumMachineState.IDLE;
                });
            items.
                Where(x =>
                x.PconMode == 8).
                ToList().
                ForEach(x =>
                {
                    x.MachineState = EnumMachineState.BLOCK;
                });
            items.
                Where(x =>
                (x.PconMode == 1 && x.IsGoods != 0) || x.PconMode == 6 || x.PconMode == 7).
                ToList().
                ForEach(x =>
                {
                    x.MachineState = EnumMachineState.RUN;
                });

            foreach (var item in items)
            {
                if (item.IsNeedReport)
                {
                    var machineName = $"{item.MachineName}{item.PortName}";
                    item.IsNeedReport = false;
                    //Thread.Sleep(50);
                    StatusChangeEvent?.Invoke(this, new StateChangeEvent()
                    {
                        MachineName = machineName,
                        MachineState = item.MachineState,
                    });
                }
            }
        }
        public bool IsRunning
        {
            get
            {
                return (MachineState == EnumMachineState.RUN || MachineState == EnumMachineState.IDLE);
            }
        }
        #region 之前多台一起上报逻辑
        public bool UpdateSrmStateByAll()
        {
            var old = MachineState;
            if (Srms.Any(x => x.DeviceMode != 1 && x.DeviceMode != 6))
            {
                this.MachineState = EnumMachineState.DOWN;
            }
            else if (Srms.All(x => (x.DeviceMode == 1 || x.DeviceMode == 6) && x.IsTask == 0) && MachineState != EnumMachineState.DOWN)
            {
                this.MachineState = EnumMachineState.IDLE;
            }
            else
            {
                this.MachineState = EnumMachineState.RUN;
            }
            var machineState = MachineState == EnumMachineState.IDLE ? EnumMachineState.RUN : MachineState;
            var oldMachineState = old == EnumMachineState.IDLE ? EnumMachineState.RUN : old;
            if (oldMachineState != machineState)
            {
                if(machineState == EnumMachineState.RUN)
                {
                    CreatTime = DateTime.Now;
                }
                IsNeedReport = true;
            }
            return old != MachineState;
        }
        #endregion
        public void UpdateWholeSrmState()
        {
            EnumMachineState machineState = MachineState;
            if (IsNeedReport)
            {
                if (CreatTime.AddSeconds(1) > DateTime.Now)
                {
                    IsNeedReport = false;
                    if (MachineState == EnumMachineState.IDLE)
                    {
                        machineState = EnumMachineState.RUN;
                    }
                    //Thread.Sleep(50);
                    StatusChangeEvent?.Invoke(this, new StateChangeEvent()
                    {
                        MachineName = NodeName,
                        MachineState = machineState,
                    });
                }
            }
        }
        public void UpdateSrmState()
        {
            Srms.
                Where(x => x.DeviceMode != 1 && x.DeviceMode != 6).
                ToList().
                ForEach(x =>
                {
                    x.MachineState = EnumMachineState.DOWN;
                });
            Srms.
              Where(x => x.DeviceMode == 1 || x.DeviceMode == 6).
              ToList().
              ForEach(x =>
              {
                  if (x.IsTask == 0)
                  {
                      x.MachineState = EnumMachineState.IDLE;
                  }
                  else
                  {
                      x.MachineState = EnumMachineState.RUN;
                  }
              });
            foreach (var srm in Srms)
            {
                if (srm.IsNeedReport)
                {
                    var machineName = $"{srm.MachineName}{srm.PortName}";
                    srm.IsNeedReport = false;
                    //Thread.Sleep(50);
                    StatusChangeEvent?.Invoke(this, new StateChangeEvent()
                    {
                        MachineName = machineName,
                        MachineState = srm.MachineState,
                    });
                }
            }
        }
        public SrmDto? GetEnabledSrm()
        {
            if (AisleMode != EnumSrmAisleMode.OneDisable) return null; ;
            return Srms?.FirstOrDefault(d => d.Enabled == 1) ?? null;
        }
        public void CalcMode()
        {
            switch (DeviceType)
            {
                case EnumNodeType.con:
                    break;
                case EnumNodeType.srm:
                    if (Srms.All(d => d.Enabled == 0))
                        AisleMode = EnumSrmAisleMode.AllDisable;
                    else if (Srms.All(d => d.Enabled == 1))
                        AisleMode = EnumSrmAisleMode.Normal;
                    else
                        AisleMode = EnumSrmAisleMode.OneDisable;
                    Console.WriteLine($"{NodeName} Mode:{AisleMode}.");
                    break;
                case EnumNodeType.rgv:
                    break;
                case EnumNodeType.lift:
                    break;
                case EnumNodeType.buffer:
                    break;
                default:
                    break;
            }
        }

        public SrmDto GetInventorySrm(EnumWcsShelfZone tz)
        {
            string port = "C2";
            if (tz == EnumWcsShelfZone.OnlyZone1 || tz == EnumWcsShelfZone.UseZone1)
            {
                port = "C1";
            }


            return Srms.FirstOrDefault(x => x.PortName == port);
        }

        public SrmDto GetExcuteSrm(EnumWcsShelfZone fz, EnumWcsShelfZone tz)
        {
            if (fz == EnumWcsShelfZone.None) throw new Exception("todo");


            string port = "";
            if (fz == EnumWcsShelfZone.OnlyZone1 || fz == EnumWcsShelfZone.UseZone1)
            {
                port = "C1";
            }
            else if (fz == EnumWcsShelfZone.OnlyZone2 || fz == EnumWcsShelfZone.UseZone2)
            {
                port = "C2";
            }
            else
            {
                if (tz == EnumWcsShelfZone.OnlyZone1 || tz == EnumWcsShelfZone.UseZone1)
                {
                    port = "C1";
                }
                else
                {
                    port = "C2";
                }
                // from在公共区域时 按to的区域判断
            }



            return Srms.FirstOrDefault(x => x.PortName == port);

            //throw new NotImplementedException();
        }

    }
}
